package com.xdjd.mobile.business.util;

import com.alibaba.fastjson.JSON;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class HttpUtil {
    private static int SocketTimeout = 60000;// 60秒
    private static int ConnectTimeout = 59000;// 59秒
    private static Boolean SetTimeOut = true;

    public static Logger logger = LoggerFactory.getLogger(HttpUtil.class);


    public static String post(String url, Map<String, String> param) {
        return post(url, null, param, "UTF-8");
    }

    public static String get(String url, String charset) {
        try {
            return get(url, null, null, charset, SocketTimeout);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String get(String url) {
        try {
            return get(url, null, null, "UTF-8", SocketTimeout);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String get(String url, Map<String, String> headers, int socketTimeout) {
        try {
            return get(url, headers, null, "UTF-8", socketTimeout);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String get(String url, Map<String, String> headers, String charset) {
        try {
            return get(url, headers, null, charset, SocketTimeout);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String get(String url, Map<String, String> headers, Map<String, String> params) {
        try {
            return get(url, headers, params, "UTF-8", SocketTimeout);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * get
     *
     * @param url     请求的url
     * @param queries 请求的参数，在浏览器？后面的数据，没有可以传null
     * @return
     * @throws IOException
     */
    public static String get(String url, Map<String, String> headers,
                             Map<String, String> queries, String charset, Integer setTimeOut) throws IOException {
        String responseBody = "";

        CloseableHttpClient httpClient = HttpClients.createDefault();
        StringBuilder sb = new StringBuilder(url);
        if (queries != null && queries.keySet().size() > 0) {
            boolean firstFlag = true;
            Iterator iterator = queries.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry<String, String>) iterator.next();
                if (firstFlag) {
                    sb.append("?" + (String) entry.getKey() + "=" + (String) entry.getValue());
                    firstFlag = false;
                } else {
                    sb.append("&" + (String) entry.getKey() + "=" + (String) entry.getValue());
                }
            }
        }
        HttpGet httpGet = new HttpGet(sb.toString());

        if (headers != null) {
            for (String key : headers.keySet()) {
                httpGet.addHeader(key, headers.get(key).toString());
            }
        }
        if (setTimeOut == null) {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SocketTimeout)
                    .setConnectTimeout(ConnectTimeout).build();// 设置请求和传输超时时间
            httpGet.setConfig(requestConfig);
        } else {

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(setTimeOut)
                    .setConnectTimeout(ConnectTimeout).build();// 设置请求和传输超时时间
            httpGet.setConfig(requestConfig);
        }
        try {
            System.out.println("Executing request " + httpGet.getRequestLine());
            // 请求数据
            CloseableHttpResponse response = httpClient.execute(httpGet);
            System.out.println(response.getStatusLine());
            int status = response.getStatusLine().getStatusCode();
            if (status == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                // do something useful with the response body
                // and ensure it is fully consumed
//				responseBody = EntityUtils.toString(entity);

                if (StringUtils.isEmpty(charset)) {
                    byte[] contentBytes = IOUtils.toByteArray(response.getEntity().getContent());
                    String htmlCharset = getHtmlCharset(response, contentBytes);
                    if (htmlCharset != null) {
                        return new String(contentBytes, htmlCharset);
                    } else {
                        return new String(contentBytes);
                    }
                } else {

                    if (charset.equalsIgnoreCase("gb2312")) {
                        charset = "GBK";
                    }

                    responseBody = IOUtils.toString(entity.getContent(), charset);
                }

                // EntityUtils.consume(entity);
            } else {
                System.out.println("http return status error:" + status);
                throw new ClientProtocolException("Unexpected response status: " + status);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            httpClient.close();
        }
        return responseBody;
    }


    public static String post(String url) {
        return post(url, null, null, null);
    }

    public static String post(String url, Map<String, String> headers, Map<String, Object> param) {
        return post(url, headers, param, "UTF-8");
    }

    public static String post(String url, Map<String, String> headers, String param) {
        return post(url, headers, param, "UTF-8");
    }

    public static String post(String url, String param) {
        return post(url, null, param, "UTF-8");
    }


    /**
     * post
     *
     * @param url     请求的url
     * @param headers 抬头
     * @param obj     form 提交的参数
     * @return
     * @throws IOException
     */
    @SuppressWarnings("unchecked")
    public static String post(String url, Map<String, String> headers, Object obj, String charset) {
        String responseBody = "";


        CloseableHttpClient httpClient = HttpClients.createDefault();

        // 指定url,和http方式
        HttpPost httpPost = new HttpPost(url);

        // 设置超时时间.
        if (SetTimeOut) {
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout).build();// 设置请求和传输超时时间
            httpPost.setConfig(requestConfig);
        }

        // haeder
        if (headers != null) {

            for (String key : headers.keySet()) {
                httpPost.addHeader(key, headers.get(key));
            }
        }

        //
        if (StringUtils.isEmpty(charset)) {
            charset = "UTF-8";
        }

        if (obj != null) {
            // 添加参数
            if (obj instanceof Map) {
                if (headers != null && headers.values().contains("application/json")) {
                    String param = JSON.toJSONString(obj, false);
                    StringEntity stringEntity = new StringEntity(param, "utf-8");
                    httpPost.setEntity(stringEntity);
                } else {
                    Map<String, Object> params = (Map<String, Object>) obj;
                    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                    for (String key : params.keySet()) {
                        nvps.add(new BasicNameValuePair(key, (String) params.get(key)));
                    }
                    httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
                }
            } else {
                StringEntity stringEntity = new StringEntity((String) obj, "utf-8");
                httpPost.setEntity(stringEntity);
            }
        }


        // 请求数据
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                HttpEntity entity = response.getEntity();
                // do something useful with the response body
                // and ensure it is fully consumed
//				responseBody = EntityUtils.toString(entity);

                responseBody = IOUtils.toString(entity.getContent(), charset);
                // EntityUtils.consume(entity);
            } else {
                responseBody = "return Exception:" + response.getStatusLine().getStatusCode()+"==="+IOUtils.toString(response.getEntity().getContent(), charset);

            }

        } catch (Exception e) {
            e.printStackTrace();
            responseBody = "return Exception:" + e.getMessage();


        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
                responseBody = "return Exception:" + e2.getMessage();
            }
        }
        return responseBody;
    }

    private static String getHtmlCharset(HttpResponse httpResponse, byte[] contentBytes) throws IOException {
        String charset;
        // charset
        // 1、encoding in http header Content-Type
        String value = httpResponse.getEntity().getContentType().getValue();
        charset = UrlUtils.getCharset(value);
        if (StringUtils.isNotBlank(charset)) {
            return charset;
        }
        // use default charset to decode first time
        Charset defaultCharset = Charset.defaultCharset();
        String content = new String(contentBytes, defaultCharset.name());
        // 2、charset in meta
        if (StringUtils.isNotEmpty(content)) {
            Document document = Jsoup.parse(content);
            Elements links = document.select("meta");
            for (Element link : links) {
                // 2.1、html4.01 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
                String metaContent = link.attr("content");
                String metaCharset = link.attr("charset");
                if (metaContent.indexOf("charset") != -1) {
                    metaContent = metaContent.substring(metaContent.indexOf("charset"), metaContent.length());
                    charset = metaContent.split("=")[1];
                    break;
                }
                // 2.2、html5 <meta charset="UTF-8" />
                else if (StringUtils.isNotEmpty(metaCharset)) {
                    charset = metaCharset;
                    break;
                }
            }
        }
        // 3、todo use tools as cpdetector for content decode
        return charset;
    }

}
